package logic

import (
	"context"
	"encoding/json"
	"fmt"
	"github.com/go-pay/gopay"
	"github.com/go-pay/gopay/alipay"
	"github.com/gogap/logs"
	"github.com/shopspring/decimal"
	"io/ioutil"
	"log"
	"net/url"
	"strconv"
	"sync"
	"time"
	"yundian/internel/alipayex"
	"yundian/internel/app/helper/request"
	"yundian/internel/app/helper/resphelper"
	"yundian/internel/app/models/orders"
	"yundian/internel/app/models/paysetting"
	"yundian/internel/pkg/dingo/global"
	"yundian/internel/pkg/utils"
)

type AliPayOrderLogic struct {
	TradeNo  string
	WxConfig *paysetting.PaySetting
}

func NewAliPayOrderLogic() *AliPayOrderLogic {
	tradeNo := utils.Join(global.Const.Pre.OrderPre, time.Now().Format("20060102150405"), utils.GetRandomInt(6))
	wxConfig := NewSettingLogic().GetAliPaySetting()
	return &AliPayOrderLogic{TradeNo: tradeNo, WxConfig: wxConfig}
}

func NewAliPayOrderLogicAppid(appid, tradeNo string) *AliPayOrderLogic {
	wxConfig := NewSettingLogic().GetPaySettingByAppid(appid)

	if tradeNo == "" {
		tradeNo = utils.Join(global.Const.Pre.OrderPre, time.Now().Format("20060102150405"), utils.GetRandomInt(6))
	}
	return &AliPayOrderLogic{TradeNo: tradeNo, WxConfig: wxConfig}
}

// 上传门店照片和视频
func (logic *AliPayOrderLogic) AliPayOfflineMaterialImageUpload(
	param *alipayex.OfflineMaterialImageUploadRes) (*alipayex.OfflineMaterialImageUploadRsp, error) {
	file, err := ioutil.ReadFile(global.Cfg.Ali.PrivateKey)
	if err != nil {
		log.Println("支付宝统一下单,获取应用密钥失败", err.Error())
		return nil, err
	}

	privateKey := string(file)
	client, _ := alipayex.NewClient(logic.WxConfig.AppId, privateKey, true)

	//配置公共参数
	client.SetCharset("utf-8").
		SetSignType(alipayex.RSA2).
		SetPrivateKeyType(alipayex.PKCS1)
	//SetNotifyUrl(logic.WxConfig.DepositNotifyUrl + param.Key)
	log.Println("配置信息", logic.WxConfig, logic.WxConfig.DepositNotifyUrl, client.NotifyUrl)

	if file, err = ioutil.ReadFile(param.ImagePath); err != nil {
		return nil, err
	}

	body := make(gopay.BodyMap)
	body.Set("image_type", param.ImageType)
	body.Set("image_name", param.ImageName)
	body.Set("image_content", file)
	//body.Set("image_pid", "2088021822217233")

	//client.DebugSwitch = 1
	aliRsp, err := client.OfflineMaterialImageUpload(context.Background(), body)
	if err != nil {
		log.Println("AliPayOfflineMaterialImageUpload-err", err.Error())
		return nil, err
	}
	return aliRsp, err
}

// 会员卡模板创建
func (logic *AliPayOrderLogic) AliPayMarketingCardTemplateCreate() (*alipayex.MarketingCardTemplateCreateRsp, error) {
	file, err := ioutil.ReadFile(global.Cfg.Ali.PrivateKey)
	if err != nil {
		log.Println("支付宝统一下单,获取应用密钥失败", err.Error())
		return nil, err
	}

	privateKey := string(file)
	client, _ := alipayex.NewClient(logic.WxConfig.AppId, privateKey, true)

	//配置公共参数
	client.SetCharset("utf-8").
		SetSignType(alipayex.RSA2).
		SetPrivateKeyType(alipayex.PKCS1)
	//SetNotifyUrl(logic.WxConfig.DepositNotifyUrl + param.Key)
	log.Println("配置信息", logic.WxConfig, logic.WxConfig.DepositNotifyUrl, client.NotifyUrl)

	//请求参数
	body := make(gopay.BodyMap)
	body.Set("request_id", "55112179")
	body.Set("card_type", "OUT_MEMBER_CARD")
	body.Set("biz_no_suffix_len", 20)
	body.Set("write_off_type", "qrcode")

	templateStyleInfo := map[string]interface{}{
		"card_show_name": "中曼会员卡",
		"logo_id":        "A*qv2iTIDyJ4AAAAAAAAAAAAAABKd2AQ",
		"background_id":  "A*_rOXS4Q9GpAAAAAAAAAAAAAABKd2AQ",
		"bg_color":       "rgb(55,112,179)",
	}
	body.Set("template_style_info", templateStyleInfo)

	columnInfoList := []map[string]interface{}{}
	columnInfoList = append(columnInfoList, map[string]interface{}{
		"code":  "BENEFIT_INFO",
		"title": "会员专享",
	})
	body.Set("column_info_list", columnInfoList)

	fieldRuleList := []map[string]interface{}{}
	fieldRuleList = append(fieldRuleList, map[string]interface{}{
		"field_name": "Balance",
		"rule_name":  "ASSIGN_FROM_REQUEST",
		"rule_value": "Balance",
	})
	body.Set("field_rule_list", fieldRuleList)

	aliRsp, err := client.MarketingCardTemplateCreate(context.Background(), body)
	if err != nil {
		log.Println("订阅消息通知发送失败", err.Error())
		return nil, err
	}
	return aliRsp, err
}

// 会员卡开卡表单模板配置
func (logic *AliPayOrderLogic) AliPayMarketingCardFormTemplateSet() (*alipayex.MarketingCardFormTemplateSetRsp, error) {
	file, err := ioutil.ReadFile(global.Cfg.Ali.PrivateKey)
	if err != nil {
		log.Println("支付宝统一下单,获取应用密钥失败", err.Error())
		return nil, err
	}

	privateKey := string(file)
	client, _ := alipayex.NewClient(logic.WxConfig.AppId, privateKey, true)

	//配置公共参数
	client.SetCharset("utf-8").
		SetSignType(alipayex.RSA2).
		SetPrivateKeyType(alipayex.PKCS1)
	//SetNotifyUrl(logic.WxConfig.DepositNotifyUrl + param.Key)
	log.Println("配置信息", logic.WxConfig, logic.WxConfig.DepositNotifyUrl, client.NotifyUrl)

	//请求参数
	body := make(gopay.BodyMap)
	body.Set("template_id", "20230412000000004559352000300724")

	fields := map[string]interface{}{
		"required": map[string]interface{}{"common_fields": []string{"OPEN_FORM_FIELD_MOBILE"}},
	}
	body.Set("fields", fields)

	aliRsp, err := client.MarketingCardFormTemplateSet(context.Background(), body)
	if err != nil {
		log.Println("会员卡开卡表单模板配置", err.Error())
		return nil, err
	}
	return aliRsp, err
}

// AliPayCreditAgreementSign 信用服务开通/授权
func (logic *AliPayOrderLogic) AliPayCreditAgreementSign() (*string, error) {
	file, err := ioutil.ReadFile(global.Cfg.Ali.PrivateKey)
	if err != nil {
		log.Println("支付宝统一下单,获取应用密钥失败", err.Error())
		return nil, err
	}

	privateKey := string(file)
	client, _ := alipayex.NewClient(logic.WxConfig.AppId, privateKey, true)

	//配置公共参数
	client.SetCharset("utf-8").
		SetSignType(alipayex.RSA2).
		SetPrivateKeyType(alipayex.PKCS1).
		SetNotifyUrl(logic.WxConfig.DepositNotifyUrl + "/credit")
	log.Println("配置信息", logic.WxConfig, logic.WxConfig.DepositNotifyUrl, client.NotifyUrl)

	//请求参数
	body := make(gopay.BodyMap)
	body.Set("out_agreement_no", logic.TradeNo)
	body.Set("zm_service_id", global.Cfg.Ali.ZmServiceId)
	body.Set("category_id", global.Cfg.Ali.ZmCategoryId)

	aliRsp, err := client.CreditPayafteruseAgreementSign(context.Background(), body)
	if err != nil {
		log.Println("信用服务开通/授权", err.Error())
		return nil, err
	}
	return aliRsp, err
}

// AliPayCreditAgreementSignQuery 查询服务开通/授权信息
func (logic *AliPayOrderLogic) AliPayCreditAgreementSignQuery(
	param *alipayex.CreditPayafteruseCreditagreementQueryRss) (
	*alipayex.CreditPayafteruseCreditagreementQueryRsp, error) {
	file, err := ioutil.ReadFile(global.Cfg.Ali.PrivateKey)
	if err != nil {
		log.Println("支付宝统一下单,获取应用密钥失败", err.Error())
		return nil, err
	}

	privateKey := string(file)
	client, _ := alipayex.NewClient(logic.WxConfig.AppId, privateKey, true)

	//配置公共参数
	client.SetCharset("utf-8").
		SetSignType(alipayex.RSA2).
		SetPrivateKeyType(alipayex.PKCS1)
	//SetNotifyUrl(logic.WxConfig.DepositNotifyUrl + param.Key)
	log.Println("配置信息", logic.WxConfig, logic.WxConfig.DepositNotifyUrl, client.NotifyUrl)

	//请求参数
	body := make(gopay.BodyMap)
	body.Set("out_agreement_no", param.OutAgreementNo)
	if param.CreditAgreementId != "" {
		body.Set("credit_agreement_id", param.CreditAgreementId)
	}

	aliRsp, err := client.CreditPayafteruseCreditagreementQuery(context.Background(), body)
	if err != nil {
		log.Println("查询服务开通/授权信息", err.Error())
		return nil, err
	}
	return aliRsp, err
}

// 执行签约
func (logic *AliPayOrderLogic) ExecUserAgreementSign() (string, error) {
	file, err := ioutil.ReadFile(global.Cfg.Ali.PrivateKey)
	if err != nil {
		log.Println("获取应用密钥失败", err.Error())
		return "", err
	}

	privateKey := string(file)
	client, _ := alipay.NewClient(logic.WxConfig.AppId, privateKey, true)
	client.SetCharset("utf-8").SetSignType(alipay.RSA2)
	log.Println("支付宝周期扣款签约，配置信息", logic.WxConfig)

	//request.setBizContent("{" +
	//	"\"sign_validity_period\":\"2m\"," +//当前用户签约请求的协议有效周期。
	//	"\"product_code\":\"CYCLE_PAY_AUTH\"," +//周期扣款销售产品码固定为CYCLE_PAY_AUTH。
	//	"\"external_logon_id\":\"13852852877\"," +//用户在商户网站的登录账号，用于在签约页面展示，如果为空，则不展示
	//	"\"personal_product_code\":\"CYCLE_PAY_AUTH_P\"," +//周期扣款个人签约产品码固定为CYCLE_PAY_AUTH_P。
	//	"\"sign_scene\":\"INDUSTRY|CARRENTAL\"," +//协议签约场景，参见 代扣产品常见场景值 。
	//	"\"external_agreement_no\":\"test\"," +//商户签约号，代扣协议中标示用户的唯一签约号（确保在商户系统中唯一）。
	//	"\"third_party_type\":\"PARTNER\"," +//签约第三方主体类型。
	//	"\"prod_params\":{" +//签约产品属性，json格式
	//	"\"auth_biz_params\":\"{\\\"platform\\\":\\\"taobao\\\"}\"" +
	//	"}," +
	//	"\"promo_params\":\"{\\\"key\\\":\\\"value\\\"}\"," +//签约营销参数，此值为json格式；具体的key需与营销约定
	//	"\"access_params\":{" +
	//	"\"channel\":\"ALIPAYAPP\"" +
	//	// 接入方式，推荐 ALIPAYAPP（支付宝h5页面签约）
	//	"}," +
	//	"\"merchant_process_url\":\"https://www.merchantpage.com/index?processId=2345678\"," +//跳转商户处理地址
	//	"\"identity_params\":{" +//用户实名信息参数
	//	"\"user_name\":\"张三\"," +
	//	"\"cert_no\":\"61102619921108888\"," +
	//	"\"identity_hash\":\"8D969EEF6ECAD3C29A3A629280E686CF0C3F5D5A86AFF3CA12020C923ADC6C92\"," +
	//	"\"sign_user_id\":\"2088202888530893\"" +
	//	"}," +
	//	"\"agreement_effect_type\":\"DIRECT\"," +//协议生效类型, 用于指定协议是立即生效还是等待商户通知再生效. 可空, 不填默认为立即生效.
	//	"\"user_age_range\":\"{\\\"min\\\":\\\"18\\\",\\\"max\\\":\\\"30\\\"}\"," +//商户希望限制的签约用户的年龄范围，min表示可签该协议的用户年龄下限，max表示年龄上限。
	//	"\"period_rule_params\":{" +//周期管控规则参数period_rule_params，在签约周期扣款产品时必传
	//	"\"period_type\":\"DAY\"," +
	//	"\"period\":9," +
	//	"\"execute_time\":\"2019-01-23\"," +//  用户签约后，下一次使用代扣支付扣款的时间。非支付并签约的成功时间。
	//	"\"single_amount\":10.99," +
	//	"\"total_amount\":600," +
	//	"\"total_payments\":12" +
	//	"}" +
	//	"}");

	body := make(gopay.BodyMap)
	body.Set("product_code", "CYCLE_PAY_AUTH")
	body.Set("personal_product_code", "CYCLE_PAY_AUTH_P")
	body.Set("sign_scene", "INDUSTRY")
	body.Set("external_agreement_no", logic.TradeNo)

	body.Set("access_params", map[string]interface{}{"channel": "ALIPAYAPP"})

	periodRuleParams := map[string]interface{}{
		"period_type":   "MONTH",
		"period":        1,
		"execute_time":  utils.AddDate(time.Now(), 0, 1).Format("2006-01-02"),
		"single_amount": 99.00,
	}
	body.Set("period_rule_params", periodRuleParams)

	aliRsp, err := client.UserAgreementPageSign(context.Background(), body)
	if err != nil {
		log.Println("周期签约失败", err.Error())
		return "", err
	}

	return aliRsp, err
}

// 支付宝 周期扣款签约(扣款并签约)
func (logic *AliPayOrderLogic) AliPayUserAgreementSign(param *request.AliPayUserAgreementSignRes) (string, error) {
	file, err := ioutil.ReadFile(global.Cfg.Ali.PrivateKey)
	if err != nil {
		log.Println("支付宝统一下单,获取应用密钥失败", err.Error())
		return "", err
	}

	privateKey := string(file)
	client, _ := alipay.NewClient(logic.WxConfig.AppId, privateKey, true)

	//配置公共参数
	client.SetCharset("utf-8").
		SetSignType(alipay.RSA2).
		SetPrivateKeyType(alipay.PKCS1).
		SetNotifyUrl(logic.WxConfig.DepositNotifyUrl + "/sing")
	log.Println("支付宝周期扣款签约，配置信息", logic.WxConfig, logic.WxConfig.DepositNotifyUrl, client.NotifyUrl)
	totalAmount, _ := decimal.NewFromInt(param.Money).Div(decimal.NewFromInt(100)).Float64()

	//请求参数
	body := make(gopay.BodyMap)
	body.Set("subject", "充电会员自动续费服务")
	body.Set("body", "会员到期前1天自动续费，自动续费可随时关闭")
	//body.Set("buyer_id", param.BuyerId)
	body.Set("out_trade_no", logic.TradeNo)
	body.Set("total_amount", totalAmount)

	body.Set("product_code", "CYCLE_PAY_AUTH")
	//t := utils.AddDate(time.Now(), 0, 1)
	//nt := t.Format("2006-01-02")
	//if t.Day() > 28 {
	//	nt = t.Format("2006-01-") + "28"
	//}
	day, _ := strconv.Atoi(global.Cfg.Ali.AutoPayDay)
	price, _ := strconv.Atoi(global.Cfg.Ali.AutoPayPrice)
	h, _ := time.ParseDuration(fmt.Sprintf("%dh", 24*day))
	nt := time.Now().Add(h).Format("2006-01-02")

	periodRuleParams := map[string]interface{}{
		"period_type":   "DAY", // MONTH DAY
		"period":        day,
		"execute_time":  nt,
		"single_amount": price,
	}
	agreementSignParams := map[string]interface{}{
		"personal_product_code": "CYCLE_PAY_AUTH_P",
		"sign_scene":            "INDUSTRY|LEASE", // 协议签约场景，商户和支付宝签约时确定
		"access_params":         map[string]interface{}{"channel": "ALIPAYAPP"},
		"period_rule_params":    periodRuleParams,
		"external_agreement_no": logic.TradeNo,
		"sign_notify_url":       logic.WxConfig.DepositNotifyUrl + "/agreement",
	}
	body.Set("agreement_sign_params", agreementSignParams)

	//公用回传参数。
	//如果请求时传递了该参数，支付宝会在异步通知时将该参数原样返回。
	//本参数必须进行UrlEncode之后才可以发送给支付宝。
	//params := url.Values{}
	//params.Add("device_info", param.DeviceSn)
	//params.Add("attach", param.BuyerId)
	//passBackParams := params.Encode()
	//body.Set("passback_params", passBackParams)

	//创建订单
	aliRsp, err := client.TradeAppPay(context.Background(), body)
	if err != nil {
		log.Println("APP 支付宝统一下单,创建订单失败", err.Error())
		return "", err
	}

	return aliRsp, err
}

// 周期性扣款协议执行计划修改
func (logic *AliPayOrderLogic) AliPayAutoExecModify(param *request.AliPayAutoTradeCreate) (*alipay.UserAgreementExecutionplanModifyRsp, error) {
	file, err := ioutil.ReadFile(logic.WxConfig.CertsPath)
	if err != nil {
		log.Println("周期性扣款协议执行计划修改", err.Error())
		return nil, err
	}

	privateKey := string(file)
	client, _ := alipay.NewClient(logic.WxConfig.AppId, privateKey, true)
	client.SetCharset("utf-8").SetSignType(alipay.RSA2).SetPrivateKeyType(alipay.PKCS1)
	log.Println("周期性扣款协议执行计划修改，配置信息", logic.WxConfig)

	body := make(gopay.BodyMap)
	body.Set("agreement_no", param.AgreementNo)
	body.Set("deduct_time", param.RenewTime)

	aliRsp, err := client.UserAgreementExecutionplanModify(context.Background(), body)
	logs.Info(body, aliRsp, err)
	return aliRsp, err
}

// 周期 自动付款订单
func (logic *AliPayOrderLogic) AliPayAutoTradeCreate(param *request.AliPayAutoTradeCreate) (*alipay.TradePayResponse, error) {
	file, err := ioutil.ReadFile(logic.WxConfig.CertsPath)
	if err != nil {
		log.Println("周期自动付款订单,获取应用密钥失败", err.Error())
		return nil, err
	}

	privateKey := string(file)
	client, _ := alipay.NewClient(logic.WxConfig.AppId, privateKey, true)
	client.SetCharset("utf-8").SetSignType(alipay.RSA2).SetPrivateKeyType(alipay.PKCS1)
	client.SetNotifyUrl(logic.WxConfig.DepositNotifyUrl + "/agreement/auto")
	log.Println("周期自动付款订单，配置信息", logic.WxConfig, client.NotifyUrl)
	totalAmount, _ := decimal.NewFromInt(param.Money).Div(decimal.NewFromInt(100)).Float64()

	// 请求参数
	body := make(gopay.BodyMap)
	body.Set("buyer_id", param.Openid)
	//body.Set("seller_id", "2088041105272721")
	body.Set("total_amount", totalAmount)
	body.Set("out_trade_no", logic.TradeNo)
	//body.Set("subject", global.Const.Desc.UnifiedBody+" 包月自动续费")
	body.Set("subject", "动能会员(退款拨打: 4006769660)")
	body.Set("product_code", "CYCLE_PAY_AUTH")

	agreementParams := map[string]interface{}{
		"agreement_no": param.AgreementNo,
	}
	body.Set("agreement_params", agreementParams)

	// 创建订单
	aliRsp, err := client.TradePay(context.Background(), body)
	logs.Info(body, aliRsp, err)
	return aliRsp, err
}

// 支付宝订单消息通知
func (logic *AliPayOrderLogic) AliPayOrderMessage(param *orders.OrderModel) (*alipayex.MerchantOrderSyncRsp, error) {
	file, err := ioutil.ReadFile(global.Cfg.Ali.PrivateKey)
	if err != nil {
		log.Println("支付宝统一下单,获取应用密钥失败", err.Error())
		return nil, err
	}

	privateKey := string(file)
	client, _ := alipayex.NewClient(logic.WxConfig.AppId, privateKey, true)

	//配置公共参数
	client.SetCharset("utf-8").
		SetSignType(alipayex.RSA2).
		SetPrivateKeyType(alipayex.PKCS1)
	//SetNotifyUrl(logic.WxConfig.DepositNotifyUrl + param.Key)
	log.Println("AliPayOrderMessage，配置信息", logic.WxConfig, logic.WxConfig.DepositNotifyUrl, client.NotifyUrl)

	//请求参数
	body := make(gopay.BodyMap)
	body.Set("out_biz_no", param.TradeNo)
	body.Set("buyer_id", param.Openid)
	body.Set("order_type", "SERVICE_ORDER")
	body.Set("order_create_time", time.Unix(int64(param.CreateAt), 0).Format("2006-01-02 15:04:05"))
	body.Set("order_modified_time", time.Unix(int64(param.UpdateAt), 0).Format("2006-01-02 15:04:05"))

	extInfo := []map[string]interface{}{}
	extInfo = append(extInfo, map[string]interface{}{"ext_key": "business_info", "ext_value": "{}"})
	extInfo = append(extInfo, map[string]interface{}{"ext_key": "merchant_biz_type", "ext_value": "3C_RENT"})
	extInfo = append(extInfo, map[string]interface{}{"ext_key": "merchant_order_status", "ext_value": "IN_THE_LEASE"})
	extInfo = append(extInfo, map[string]interface{}{"ext_key": "merchant_order_link_page", "ext_value": "/pages/serviceHome/serviceHome"})
	extInfo = append(extInfo, map[string]interface{}{"ext_key": "tiny_app_id", "ext_value": logic.WxConfig.AppId})
	body.Set("ext_info", extInfo)

	itemOrderList := []map[string]interface{}{}
	itemOrderList = append(itemOrderList, map[string]interface{}{"quantity": 1, "item_name": global.Const.Desc.UnifiedBody})
	body.Set("item_order_list", itemOrderList)

	aliRsp, err := client.MerchantOrderSync(context.Background(), body)
	if err != nil {
		log.Println("订单状态同步失败", err.Error())
		return nil, err
	}
	return aliRsp, err
}

// 支付宝订阅消息通知
func (logic *AliPayOrderLogic) AliPaySubscribeMessage(param *orders.OrderModel) (*alipayex.OpenAppMiniTemplateMessageSendRsp, error) {
	file, err := ioutil.ReadFile(global.Cfg.Ali.PrivateKey)
	if err != nil {
		log.Println("支付宝统一下单,获取应用密钥失败", err.Error())
		return nil, err
	}

	privateKey := string(file)
	client, _ := alipayex.NewClient(logic.WxConfig.AppId, privateKey, true)

	//配置公共参数
	client.SetCharset("utf-8").
		SetSignType(alipayex.RSA2).
		SetPrivateKeyType(alipayex.PKCS1)
	//SetNotifyUrl(logic.WxConfig.DepositNotifyUrl + param.Key)
	log.Println("AliPayOrderMessage，配置信息", logic.WxConfig, logic.WxConfig.DepositNotifyUrl, client.NotifyUrl)

	//请求参数
	body := make(gopay.BodyMap)
	body.Set("to_user_id", param.Openid)
	body.Set("user_template_id", "2f2dcf2f100440328bf97aa049e0e02c")
	body.Set("page", "/pages/serviceHome/serviceHome")

	dataInfo := map[string]interface{}{
		"keyword1": map[string]interface{}{"value": global.Const.Desc.UnifiedNameBody},
		"keyword2": map[string]interface{}{"value": param.PlaceName},
		"keyword3": map[string]interface{}{"value": time.Unix(int64(param.CreateAt), 0).Format("2006-01-02 15:04:05")},
		"keyword4": map[string]interface{}{"value": param.TradeNo},
		"keyword5": map[string]interface{}{"value": "使用完成后，请重新扫码归还"},
	}
	body.Set("data", dataInfo)

	aliRsp, err := client.OpenAppMiniTemplateMessageSend(context.Background(), body)
	if err != nil {
		log.Println("订阅消息通知发送失败", err.Error())
		return nil, err
	}
	return aliRsp, err
}

func (logic *AliPayOrderLogic) AliPayTradeCreateCommon(param *request.AliPayTradeCreateOrder) (*resphelper.AliPayTradeCreateOrderRes, error) {
	file, err := ioutil.ReadFile(global.Cfg.Ali.PrivateKey)
	if err != nil {
		log.Println("支付宝统一下单,获取应用密钥失败", err.Error())
		return nil, err
	}
	// 请求参数
	privateKey := string(file)
	client, _ := alipay.NewClient(logic.WxConfig.AppId, privateKey, true)
	//配置公共参数
	client.SetCharset("utf-8").
		SetSignType(alipay.RSA2).
		SetPrivateKeyType(alipay.PKCS1).
		SetNotifyUrl(logic.WxConfig.DepositNotifyUrl + param.Key)
	log.Println("支付宝统一下单，配置信息", logic.WxConfig, logic.WxConfig.DepositNotifyUrl, client.NotifyUrl)
	totalAmount, _ := decimal.NewFromInt(param.Money).Div(decimal.NewFromInt(100)).Float64()

	//请求参数
	body := make(gopay.BodyMap)
	body.Set("subject", param.PaySubject)
	body.Set("buyer_id", param.BuyerId)
	body.Set("out_trade_no", logic.TradeNo)
	body.Set("total_amount", totalAmount)

	//公用回传参数。
	//如果请求时传递了该参数，支付宝会在异步通知时将该参数原样返回。
	//本参数必须进行UrlEncode之后才可以发送给支付宝。
	params := url.Values{}
	params.Add("device_info", param.DeviceSn)
	params.Add("attach", param.ProductId)
	passBackParams := params.Encode()
	body.Set("passback_params", passBackParams)

	//创建订单
	aliRsp, err := client.TradeCreate(context.Background(), body)
	if err != nil {
		log.Println("支付宝统一下单,创建订单失败", err.Error())
		return nil, err
	}
	aliPayTradeCreateOrderRes := &resphelper.AliPayTradeCreateOrderRes{}
	aliPayTradeCreateOrderRes.Sign = aliRsp.Sign
	aliPayTradeCreateOrderRes.AliPayTradeCreateResBody.TradeNo = aliRsp.Response.OutTradeNo
	aliPayTradeCreateOrderRes.AliPayTradeCreateResBody.OutTradeNo = aliRsp.Response.TradeNo
	aliPayTradeCreateOrderRes.AliPayTradeCreateResBody.Code = aliRsp.Response.Code
	aliPayTradeCreateOrderRes.AliPayTradeCreateResBody.Msg = aliRsp.Response.Msg
	return aliPayTradeCreateOrderRes, err
}

// 支付宝 统一收单交易创建接口
func (logic *AliPayOrderLogic) AliPayTradeCreate(param *request.AliPayTradeCreateOrder) (*resphelper.AliPayTradeCreateOrderRes, error) {
	file, err := ioutil.ReadFile(global.Cfg.Ali.PrivateKey)
	if err != nil {
		log.Println("支付宝统一下单,获取应用密钥失败", err.Error())
		return nil, err
	}
	// 请求参数
	privateKey := string(file)
	//初始化支付宝客户端
	//    appId：应用ID
	//    privateKey：应用私钥，支持PKCS1和PKCS8
	//    isProd：是否是正式环境
	client, _ := alipay.NewClient(logic.WxConfig.AppId, privateKey, true)
	//配置公共参数
	client.SetCharset("utf-8").
		SetSignType(alipay.RSA2).
		SetPrivateKeyType(alipay.PKCS1).
		SetNotifyUrl(logic.WxConfig.DepositNotifyUrl)
	log.Println("支付宝统一下单，配置信息", logic.WxConfig, logic.WxConfig.DepositNotifyUrl, client.NotifyUrl)
	totalAmount, _ := decimal.NewFromInt(param.Money).Div(decimal.NewFromInt(100)).Float64()

	//请求参数
	body := make(gopay.BodyMap)
	body.Set("subject", global.Const.Desc.UnifiedBody)
	//body.Set("buyer_id", param.BuyerId)
	body.Set("buyer_open_id", param.BuyerId)
	body.Set("out_trade_no", logic.TradeNo)
	body.Set("total_amount", totalAmount)

	//公用回传参数。
	//如果请求时传递了该参数，支付宝会在异步通知时将该参数原样返回。
	//本参数必须进行UrlEncode之后才可以发送给支付宝。
	params := url.Values{}
	params.Add("device_info", param.DeviceSn)
	params.Add("attach", param.ProductId)
	passBackParams := params.Encode()
	body.Set("passback_params", passBackParams)

	//创建订单
	aliRsp, err := client.TradeCreate(context.Background(), body)
	if err != nil {
		log.Println("支付宝统一下单,创建订单失败", err.Error())
		return nil, err
	}
	aliPayTradeCreateOrderRes := &resphelper.AliPayTradeCreateOrderRes{}
	aliPayTradeCreateOrderRes.Sign = aliRsp.Sign
	aliPayTradeCreateOrderRes.AliPayTradeCreateResBody.TradeNo = aliRsp.Response.OutTradeNo
	aliPayTradeCreateOrderRes.AliPayTradeCreateResBody.OutTradeNo = aliRsp.Response.TradeNo
	aliPayTradeCreateOrderRes.AliPayTradeCreateResBody.Code = aliRsp.Response.Code
	aliPayTradeCreateOrderRes.AliPayTradeCreateResBody.Msg = aliRsp.Response.Msg
	return aliPayTradeCreateOrderRes, err
}

// APP 统一收单交易创建接口
func (logic *AliPayOrderLogic) AppAliPayTradeCreate(param *request.AliPayTradeCreateOrder) (string, error) {
	file, err := ioutil.ReadFile(global.Cfg.Ali.PrivateKey)
	if err != nil {
		log.Println("支付宝统一下单,获取应用密钥失败", err.Error())
		return "", err
	}
	// 请求参数
	privateKey := string(file)
	//初始化支付宝客户端
	//    appId：应用ID
	//    privateKey：应用私钥，支持PKCS1和PKCS8
	//    isProd：是否是正式环境
	client, _ := alipay.NewClient(logic.WxConfig.AppId, privateKey, true)
	//配置公共参数
	client.SetCharset("utf-8").
		SetSignType(alipay.RSA2).
		SetPrivateKeyType(alipay.PKCS1).
		SetNotifyUrl(logic.WxConfig.DepositNotifyUrl)
	log.Println("支付宝统一下单，配置信息", logic.WxConfig, logic.WxConfig.DepositNotifyUrl, client.NotifyUrl)
	totalAmount, _ := decimal.NewFromInt(param.Money).Div(decimal.NewFromInt(100)).Float64()

	//请求参数
	body := make(gopay.BodyMap)
	body.Set("subject", global.Const.Desc.UnifiedBody)
	body.Set("buyer_id", param.BuyerId)
	body.Set("out_trade_no", logic.TradeNo)
	body.Set("total_amount", totalAmount)

	//公用回传参数。
	//如果请求时传递了该参数，支付宝会在异步通知时将该参数原样返回。
	//本参数必须进行UrlEncode之后才可以发送给支付宝。
	params := url.Values{}
	params.Add("device_info", param.DeviceSn)
	params.Add("attach", param.ProductId)
	passBackParams := params.Encode()
	body.Set("passback_params", passBackParams)

	//创建订单
	aliRsp, err := client.TradeAppPay(context.Background(), body)
	if err != nil {
		log.Println("APP 支付宝统一下单,创建订单失败", err.Error())
		return "", err
	}

	return aliRsp, err
}

//如果需要部分退款需要在 退款中加上out_request_no参数，需要保持唯一性
//out_request_no：标识一次退款请求，同一笔交易多次退款需要保证唯一，如需部分退款，则此参数必传。
//支付宝 统一收单交易退款接口
func (logic *AliPayOrderLogic) AliPayTradeRefund(returnMoney int64, outTradeNo, refundDesc string) (*alipay.TradeRefundResponse, error) {
	file, err := ioutil.ReadFile(logic.WxConfig.CertsPath)
	if err != nil {
		log.Println("支付宝统一收单交易退款接口,获取应用密钥失败", err.Error())
		return nil, err
	}

	log.Println("开始异步退款,")
	// 请求参数
	privateKey := string(file)
	//初始化支付宝客户端
	//    appId：应用ID
	//    privateKey：应用私钥，支持PKCS1和PKCS8
	//    isProd：是否是正式环境
	client, _ := alipay.NewClient(logic.WxConfig.AppId, privateKey, true)
	//配置公共参数
	client.SetCharset("utf-8").
		SetSignType(alipay.RSA2).
		SetPrivateKeyType(alipay.PKCS1)

	//SetNotifyUrl(logic.WxConfig.DepositNotifyUrl)
	// 请求参数

	refundAmount, _ := decimal.NewFromInt(returnMoney).Div(decimal.NewFromInt(100)).Float64()

	bm := make(gopay.BodyMap)
	bm.Set("out_trade_no", logic.TradeNo).
		Set("refund_amount", refundAmount).
		Set("refund_reason", refundDesc).
		Set("out_request_no", outTradeNo)

	// 发起退款请求
	aliRsp, err := client.TradeRefund(context.Background(), bm)
	logs.Info("支付宝退款返回", aliRsp.Response.Msg, err)

	return aliRsp, err
}

//支付宝 统一收单线下交易查询
func (logic *AliPayOrderLogic) AliPayTradeOrdersQuery(tradeNo string) (*resphelper.TradeQueryResponse, error) {
	file, err := ioutil.ReadFile(global.Cfg.Ali.PrivateKey)
	if err != nil {
		log.Println("支付宝统一下单,获取应用密钥失败", err.Error())
		return nil, err
	}
	// 请求参数
	privateKey := string(file)
	//初始化支付宝客户端
	//    appId：应用ID
	//    privateKey：应用私钥，支持PKCS1和PKCS8
	//    isProd：是否是正式环境
	client, _ := alipay.NewClient(logic.WxConfig.AppId, privateKey, true)
	//配置公共参数
	client.SetCharset("utf-8").
		SetSignType(alipay.RSA2).
		SetPrivateKeyType(alipay.PKCS1)

	//请求参数
	body := make(gopay.BodyMap)
	//body.Set("trade_no", tradeNo)
	body.Set("out_trade_no", tradeNo)

	//查询订单
	aliRsp, err := client.TradeQuery(context.Background(), body)
	if err != nil {
		log.Println("统一收单线下交易查询,查询订单请求失败", tradeNo, err.Error())
		return nil, err
	}

	queryInfo := &resphelper.TradeQueryResponse{}

	resByte, _ := json.Marshal(aliRsp)
	json.Unmarshal(resByte, queryInfo)
	log.Println("统一收单线下交易查询,返回信息", queryInfo)

	return queryInfo, nil
}

//资金授权解冻接口
func (logic *AliPayOrderLogic) AliPayOrderUnfreeze(param *request.OrderUnfreezeReq) (*resphelper.FundAuthOrderUnfreezeResponse, error) {
	file, err := ioutil.ReadFile(global.Cfg.Ali.PrivateKey)
	if err != nil {
		log.Println("支付宝资金授权解冻接口,获取应用密钥失败", err.Error())
		return nil, err
	}
	// 请求参数
	privateKey := string(file)
	//初始化支付宝客户端
	//    appId：应用ID
	//    privateKey：应用私钥，支持PKCS1和PKCS8
	//    isProd：是否是正式环境
	client, _ := alipay.NewClient(logic.WxConfig.AppId, privateKey, true)
	//配置公共参数
	client.SetCharset("utf-8").
		SetSignType(alipay.RSA2).
		SetPrivateKeyType(alipay.PKCS1).
		SetNotifyUrl(logic.WxConfig.DepositNotifyUrl)
	log.Println("资金授权解冻接口，配置信息", logic.WxConfig, logic.WxConfig.DepositNotifyUrl, client.NotifyUrl)

	amount, _ := decimal.NewFromInt(param.Amount).Div(decimal.NewFromInt(100)).Float64()
	//请求参数
	body := make(gopay.BodyMap)
	body.Set("auth_no", param.Amount)
	body.Set("out_request_no", param.OutRequestNo)
	body.Set("amount", amount)
	body.Set("remark", param.Remark)
	body.Set("extra_param", param.ExtraParam)
	aliRsp, err := client.FundAuthOrderUnfreeze(context.Background(), body)
	if err != nil {
		log.Println("支付宝资金授权解冻接口,发起退款请求失败", err)
		return nil, err
	}
	res := &resphelper.FundAuthOrderUnfreezeResponse{}
	resByte, _ := json.Marshal(aliRsp)
	json.Unmarshal(resByte, res)
	log.Println("资金授权解冻接口,返回信息", res)
	return res, nil

}

//订单信息同步
func (logic *AliPayOrderLogic) AliPayOrderInfoSync(param *request.OrderInfoSync) (*resphelper.TradeOrderInfoSyncRsp, error) {
	file, err := ioutil.ReadFile(global.Cfg.Ali.PrivateKey)
	if err != nil {
		log.Println("支付宝订单信息同步,获取应用密钥失败", err.Error())
		return nil, err
	}
	// 请求参数
	privateKey := string(file)
	logs.Info("privateKey", privateKey, logic.WxConfig.AppId)
	//初始化支付宝客户端
	//    appId：应用ID
	//    privateKey：应用私钥，支持PKCS1和PKCS8
	//    isProd：是否是正式环境
	client, _ := alipay.NewClient(logic.WxConfig.AppId, privateKey, true)
	logs.Info(1111111111111111)
	//配置公共参数
	client.SetCharset("utf-8").
		SetSignType(alipay.RSA2).
		SetPrivateKeyType(alipay.PKCS1).
		SetNotifyUrl(logic.WxConfig.DepositNotifyUrl)
	//log.Println("订单信息同步，配置信息", logic.WxConfig, logic.WxConfig.DepositNotifyUrl, client.NotifyUrl)
	orderBizInfo := &struct {
		Status string `json:"status"`
	}{}

	orderBizInfo.Status = "COMPLETE"

	byteData, _ := json.Marshal(orderBizInfo)

	//请求参数
	body := make(gopay.BodyMap)
	body.Set("trade_no", param.TradeNo)
	body.Set("out_request_no", param.OutRequestNo)
	body.Set("biz_type", "CREDIT_AUTH")
	body.Set("order_biz_info", string(byteData))
	//logs.Info("请求参数", body, "order_biz_info", orderBizInfo.Status)
	aliRsp, err := client.TradeOrderInfoSync(context.Background(), body)
	if err != nil {
		log.Println("支付宝订单信息同步,发起退款请求失败", err)
		return nil, err
	}
	res := &resphelper.TradeOrderInfoSyncRsp{}
	resByte, _ := json.Marshal(aliRsp)
	json.Unmarshal(resByte, res)
	log.Println("订单信息同步,返回信息", res)
	return res, nil

}

//资金授权操作查询接口
func (logic *AliPayOrderLogic) AliPayFundAuthOperationDetailQuery(param *request.FundAuthOperationDetailQuery) (*resphelper.FundAuthOperationDetailQueryResponse, error) {
	file, err := ioutil.ReadFile(global.Cfg.Ali.PrivateKey)
	if err != nil {
		log.Println("支付宝订单信息同步,获取应用密钥失败", err.Error())
		return nil, err
	}
	// 请求参数
	privateKey := string(file)
	//初始化支付宝客户端
	//    appId：应用ID
	//    privateKey：应用私钥，支持PKCS1和PKCS8
	//    isProd：是否是正式环境
	client, _ := alipay.NewClient(logic.WxConfig.AppId, privateKey, true)
	//配置公共参数
	client.SetCharset("utf-8").
		SetSignType(alipay.RSA2).
		SetPrivateKeyType(alipay.PKCS1).
		SetNotifyUrl(logic.WxConfig.DepositNotifyUrl)
	log.Println("资金授权操作查询，配置信息", logic.WxConfig, logic.WxConfig.DepositNotifyUrl, client.NotifyUrl)

	//请求参数
	body := make(gopay.BodyMap)
	body.Set("auth_no", param.AuthNo)
	body.Set("out_request_no", param.OutRequestNo)
	body.Set("operation_type", param.OperationType)
	body.Set("out_order_no", param.OutOrderNo)
	aliRsp, err := client.FundAuthOperationDetailQuery(context.Background(), body)
	if err != nil {
		log.Println("支付宝订单信息同步,发起退款请求失败", err)
		return nil, err
	}
	res := &resphelper.FundAuthOperationDetailQueryResponse{}
	resByte, _ := json.Marshal(aliRsp)
	json.Unmarshal(resByte, res)
	log.Println("资金授权操作查询,返回信息", res)
	return res, nil
}

// 订单查询协议状态
func (logic *AliPayOrderLogic) AliPayNoAgreementNoOrderQuery(alipayUserId, tradeNo string) (agreement_no, status string) {
	file, err := ioutil.ReadFile(logic.WxConfig.CertsPath)
	if err != nil {
		log.Println("获取应用密钥失败", err.Error())
		return "", ""
	}
	logs.Info("logic.WxConfig.AppId", logic.WxConfig.AppId, logic.WxConfig.CertsPath)
	privateKey := string(file)
	client, _ := alipay.NewClient(logic.WxConfig.AppId, privateKey, true)

	//配置公共参数
	client.SetCharset("utf-8").
		SetSignType(alipay.RSA2).
		SetPrivateKeyType(alipay.PKCS1)

	//请求参数
	body := make(gopay.BodyMap)
	body.Set("alipay_user_id", alipayUserId)
	//body.Set("product_code", "CYCLE_PAY_AUTH")
	body.Set("personal_product_code", "CYCLE_PAY_AUTH_P")
	body.Set("sign_scene", "INDUSTRY|LEASE")
	body.Set("third_party_type", "PARTNER")
	//body.Set("external_agreement_no", tradeNo)
	//body.Set("external_agreement_no", "20225403875663427999")
	//body.Set("external_agreement_no", "ZM20220624032458942334")

	//body.Set("agreement_no", "20225623859563687553")

	logs.Info("gopay.BodyMap", alipayUserId)

	var wg sync.WaitGroup
	wg.Add(1)
	go func() {
		defer wg.Done()
		aliRsp, err := client.UserAgreementQuery(context.Background(), body)
		if aliRsp != nil {
			logs.Info("11111111111111", aliRsp.Response.Code, aliRsp.Response.Msg, aliRsp.Response.SubCode, aliRsp.Response.SubMsg)
			logs.Info(aliRsp.Response.AgreementNo, aliRsp.Response.Status)
		} else {
			logs.Info("333333333333333333")
		}
		if err != nil {
			logs.Info("2222222222", err.Error())
			//return "", ""
		}
	}()
	wg.Wait()
	time.Sleep(time.Second * 5)
	return "", ""
	//return aliRsp.Response.AgreementNo, aliRsp.Response.Status
}
